"""
并发STT服务管理器
实现基于线程池的并发语音转文本处理，支持最大并发数限制
"""
import threading
import time
from concurrent.futures import ThreadPoolExecutor, TimeoutError

import config
# 导入STT工厂类
from src.stt.factory import STTFactory
# 导入日志工具
from ..utils.logger import get_logger, set_request_id_for_logger, get_current_request_id


class ConcurrentSTTManager:
    """
    并发STT服务管理器
    
    负责管理Whisper模型的并发处理，通过线程池限制最大并发数，
    超出限制的请求会排队等待处理。
    """

    def __init__(self, max_workers=None):
        """
        初始化并发STT管理器
        
        Args:
            max_workers (int, optional): 最大工作线程数（并发数），
                                       如果为None则从config读取
        """
        # 从配置文件读取最大并发数
        if max_workers is None:
            max_workers = config.WHISPER_MAX_CONCURRENT

        # 初始化日志记录器
        self.logger = get_logger(__name__)
        # 设置最大工作线程数
        self.max_workers = max_workers
        # 创建线程池执行器
        self.executor = ThreadPoolExecutor(max_workers=max_workers)
        # 创建线程锁
        self._lock = threading.Lock()
        # 当前活跃请求计数
        self._request_count = 0

        self.logger.info("初始化并发STT管理器，最大并发数: %d", max_workers)

    def process_audio(self, audio_file_path, language=None, timeout=config.GRPC_MAX_TIMEOUT):
        """
        并发处理音频文件转文本
        
        Args:
            audio_file_path (str): 音频文件路径
            language (str, optional): 音频语言，None则自动检测
            timeout (int, optional): 超时时间（秒）
            
        Returns:
            tuple: (code, text, result_info)
                - code (int): 状态码
                - text (str): 识别文本
                - result_info (dict): 详细信息
        """
        # 获取当前线程的request_id并传递到线程池
        current_request_id = get_current_request_id()
        
        self.logger.info("开始处理音频: %s, 语言: %s, 超时: %d秒, request_id: %s",
                         audio_file_path, language, timeout, current_request_id)

        try:
            # 提交任务到线程池，传递request_id
            future = self.executor.submit(
                self._process_single_audio,
                audio_file_path,
                language,
                current_request_id
            )

            # 等待结果，设置超时
            result = future.result(timeout=timeout)
            return result

        except TimeoutError as te:
            self.logger.error("STT处理超时: %s (timeout=%d秒, request_id: %s)", 
                              audio_file_path, timeout, current_request_id)
            raise te
        except Exception as e:
            self.logger.error("STT处理异常: %s, 错误: %s, request_id: %s", 
                              audio_file_path, str(e), current_request_id)
            raise e

    def _process_single_audio(self, audio_file_path, language, request_id):
        """
        单线程处理音频转文本（在线程池中执行）
        
        Args:
            audio_file_path (str): 音频文件路径
            language (str): 音频语言
            request_id (str): 请求ID，用于日志追踪
            
        Returns:
            tuple: (code, text, result_info)
        """
        try:
            # 在线程池中设置request_id
            set_request_id_for_logger(request_id)
            
            # 记录当前活跃线程数
            with self._lock:
                self._request_count += 1
                current_active = self._request_count

            self.logger.info("开始处理音频: %s, 当前活跃请求数: %d, request_id: %s",
                             audio_file_path, current_active, request_id)

            # 使用工厂模式获取STT实现实例
            start_time = time.time()
            stt_service = STTFactory.create_implementation()
            factory_time = time.time() - start_time

            self.logger.info("STT实现创建完成，耗时: %.2f秒", factory_time)

            # 执行语音转文本
            start_time = time.time()
            code, result_info = stt_service.speech_to_text(
                audio_file_path,
                language=language
            )
            process_time = time.time() - start_time

            # 补充结果信息
            result_info.update({
                "audio_file": audio_file_path,
                "language": language or "auto",
                "factory_time": factory_time,
                "process_time": process_time,
                "total_time": factory_time + process_time
            })

            self.logger.info("处理完成: %s, 耗时: %.2f秒, 状态码: %d, request_id: %s",
                             audio_file_path, process_time, code, request_id)

            return code, result_info

        except Exception as e:
            self.logger.error("处理失败: %s, 错误: %s, request_id: %s",
                              audio_file_path, str(e), request_id)
            raise e
        finally:
            # 减少活跃计数
            with self._lock:
                self._request_count -= 1

    def get_status(self):
        """
        获取当前状态信息
        
        Returns:
            dict: 包含当前活跃请求数、队列状态等信息
        """
        with self._lock:
            return {
                "max_workers": self.max_workers,
                "current_active_requests": self._request_count,
                "queue_size": len(self.executor._work_queue) if hasattr(self.executor, '_work_queue') else 0
            }

    def shutdown(self):
        """
        优雅关闭线程池
        """
        self.logger.info("开始关闭并发STT管理器...")
        # 关闭线程池执行器
        self.executor.shutdown(wait=True)
        self.logger.info("并发STT管理器已关闭")

    def __del__(self):
        """
        析构函数，确保资源清理
        """
        try:
            self.shutdown()
        except:
            pass


# 创建全局实例
_concurrent_stt_manager = None


def get_concurrent_stt_manager():
    """
    获取并发STT管理器单例
    
    Returns:
        ConcurrentSTTManager: 并发STT管理器实例
    """
    global _concurrent_stt_manager
    # 如果实例不存在则创建新实例
    if _concurrent_stt_manager is None:
        _concurrent_stt_manager = ConcurrentSTTManager()
    return _concurrent_stt_manager


def process_audio_concurrently(audio_file_path, language=None, timeout=config.GRPC_MAX_TIMEOUT):
    """
    便捷的并发处理函数
    
    Args:
        audio_file_path (str): 音频文件路径
        language (str, optional): 音频语言
        timeout (int, optional): 超时时间
        
    Returns:
        tuple: (code, text, result_info)
    """
    # 获取并发管理器实例
    manager = get_concurrent_stt_manager()
    # 调用并发处理方法
    return manager.process_audio(audio_file_path, language, timeout)
